home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / ibus-table / engine / tabsqlitedb.pyc (.txt) < prev   
Python Compiled Bytecode  |  2009-10-28  |  42KB  |  1,019 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import os
  5. import os.path as path
  6. from sys import stderr
  7. import sqlite3
  8. import tabdict
  9. import uuid
  10. import time
  11. import re
  12. patt_r = re.compile('c([ea])(\\d):(.*)')
  13. patt_p = re.compile('p(-{0,1}\\d)(\\d)')
  14.  
  15. class tabsqlitedb:
  16.     '''Phrase database for tables'''
  17.     
  18.     def __init__(self, name = 'table.db', user_db = None, filename = None):
  19.         self.parse = tabdict.parse
  20.         self.deparse = tabdict.deparse
  21.         self._add_phrase_sqlstr = ''
  22.         self.old_phrases = []
  23.         self.ime_property_cache = { }
  24.         if filename:
  25.             self.db = sqlite3.connect(filename)
  26.         else:
  27.             
  28.             try:
  29.                 os.system('cat %s > /dev/null' % name)
  30.             except:
  31.                 pass
  32.  
  33.             self.db = sqlite3.connect(name)
  34.         
  35.         try:
  36.             self.db.execute('PRAGMA page_size = 8192; ')
  37.             self.db.execute('PRAGMA cache_size = 20000; ')
  38.             self.db.execute('PRAGMA temp_store = MEMORY; ')
  39.             self.db.execute('PRAGMA synchronous = OFF; ')
  40.         except:
  41.             print 'encountering error when init db'
  42.  
  43.         self.db.executescript('CREATE TABLE IF NOT EXISTS main.ime (attr TEXT, val TEXT);')
  44.         if not self.db.execute('SELECT val FROM main.ime             WHERE attr="name";').fetchall():
  45.             ime_keys = {
  46.                 'name': '',
  47.                 'name.zh_cn': '',
  48.                 'name.zh_hk': '',
  49.                 'name.zh_tw': '',
  50.                 'author': 'somebody',
  51.                 'uuid': '%s' % uuid.uuid4(),
  52.                 'serial_number': '%s' % time.strftime('%Y%m%d'),
  53.                 'icon': 'ibus-table.svg',
  54.                 'license': 'LGPL',
  55.                 'languages': '',
  56.                 'valid_input_chars': 'abcdefghijklmnopqrstuvwxyz',
  57.                 'max_key_length': '4',
  58.                 'status_prompt': '',
  59.                 'def_full_width_punct': 'TRUE',
  60.                 'def_full_width_letter': 'FALSE',
  61.                 'user_can_define_phrase': 'FALSE',
  62.                 'pinyin_mode': 'FALSE',
  63.                 'dynamic_adjust': 'FALSE',
  64.                 'auto_commit': 'false',
  65.                 'description': 'A IME under IBus Table',
  66.                 'layout': 'us',
  67.                 'rules': '' }
  68.             for _name in ime_keys:
  69.                 sqlstr = 'INSERT INTO main.ime (attr,val) VALUES (?,?);'
  70.                 self.db.execute(sqlstr, (_name, ime_keys[_name]))
  71.             
  72.         
  73.         self._mlen = int(self.get_ime_property('max_key_length'))
  74.         self._is_chinese = self.is_chinese()
  75.         self._set_add_phrase_sqlstr()
  76.         self._pt_index = [
  77.             'id',
  78.             'mlen',
  79.             'clen']
  80.         for i in range(self._mlen):
  81.             self._pt_index.append('m%d' % i)
  82.         
  83.         if self._is_chinese:
  84.             self._pt_index += [
  85.                 'category']
  86.         
  87.         self._pt_index += [
  88.             'phrase',
  89.             'freq',
  90.             'user_freq']
  91.         self.user_can_define_phrase = self.get_ime_property('user_can_define_phrase')
  92.         if self.user_can_define_phrase:
  93.             if self.user_can_define_phrase.lower() == u'true':
  94.                 self.user_can_define_phrase = True
  95.             else:
  96.                 self.user_can_define_phrase = False
  97.         else:
  98.             print 'Could not find "user_can_define_phrase" entry from database, is it a outdated database?'
  99.             self.user_can_define_phrase = False
  100.         self.dynamic_adjust = self.get_ime_property('dynamic_adjust')
  101.         if self.dynamic_adjust:
  102.             if self.dynamic_adjust.lower() == u'true':
  103.                 self.dynamic_adjust = True
  104.             else:
  105.                 self.dynamic_adjust = False
  106.         else:
  107.             print 'Could not find "dynamic_adjust" entry from database, is it a outdated database?'
  108.             self.dynamic_adjust = False
  109.         self.rules = self.get_rules()
  110.         self.pkeylens = []
  111.         if self.rules:
  112.             self.pkeylens = self.phrase_keys_len()
  113.         
  114.         self._goucima = { }
  115.         if filename:
  116.             return None
  117.         
  118.         try:
  119.             self.db.execute('ATTACH DATABASE "%s" AS user_db;' % user_db)
  120.         except:
  121.             None if user_db != None else filename
  122.             print >>stderr, 'The user database was damaged. We will recreate it!'
  123.             os.rename(user_db, '%s.%d' % (user_db, os.getpid()))
  124.             self.init_user_db(user_db)
  125.             self.db.execute('ATTACH DATABASE "%s" AS user_db;' % user_db)
  126.  
  127.         self.create_tables('user_db')
  128.         if self.old_phrases:
  129.             phrases = filter((lambda x: x[0] > 1), self.old_phrases)
  130.             phrases = (map,)((lambda x: [
  131. self.parse_phrase_to_tabkeys(x[1])] + list(x[1:])), phrases)
  132.             map(self.u_add_phrase, phrases)
  133.             self.db.commit()
  134.         
  135.         self.create_indexes('user_db', commit = False)
  136.         self.generate_userdb_desc()
  137.         mudb = ':memory:'
  138.         self.db.execute('ATTACH DATABASE "%s" AS mudb;' % mudb)
  139.         self.create_tables('mudb')
  140.  
  141.     
  142.     def update_phrase(self, entry, database = 'user_db'):
  143.         '''update phrase freqs'''
  144.         _con = [
  145.             entry[-1]] + list(entry[1:3 + entry[1]]) + [
  146.             entry[-3]]
  147.         _condition = u''.join(map((lambda x: 'AND m%d = ? ' % x), range(entry[1])))
  148.         sqlstr = 'UPDATE %s.phrases SET user_freq = ? WHERE mlen = ? AND clen = ? %s AND phrase = ?;' % (database, _condition)
  149.         self.db.execute(sqlstr, _con)
  150.         self.db.commit()
  151.  
  152.     
  153.     def sync_usrdb(self):
  154.         mudata = self.db.execute('SELECT * FROM mudb.phrases;').fetchall()
  155.         data_u = filter((lambda x: x[-2] in (1, -3)), mudata)
  156.         data_a = filter((lambda x: x[-2] == 2), mudata)
  157.         data_n = filter((lambda x: x[-2] == -2), mudata)
  158.         data_a = (map,)((lambda x: (u''.join(map(self.deparse, x[3:3 + x[1]])), x[-3], 0, x[-1])), data_a)
  159.         data_n = (map,)((lambda x: (u''.join(map(self.deparse, x[3:3 + x[1]])), x[-3], -1, x[-1])), data_n)
  160.         map(self.update_phrase, data_u)
  161.         map(self.u_add_phrase, data_a)
  162.         map(self.u_add_phrase, data_n)
  163.         self.db.commit()
  164.  
  165.     
  166.     def is_chinese(self):
  167.         _tabsqlitedb__lang = self.get_ime_property('languages')
  168.         if _tabsqlitedb__lang:
  169.             _tabsqlitedb__langs = _tabsqlitedb__lang.split(',')
  170.             for _l in _tabsqlitedb__langs:
  171.                 if _l.lower().find('zh') != -1:
  172.                     return True
  173.             
  174.         
  175.         return False
  176.  
  177.     
  178.     def create_tables(self, database):
  179.         '''Create tables that contain all phrase'''
  180.         
  181.         try:
  182.             self.db.execute('PRAGMA cache_size = 20000; ')
  183.         except:
  184.             pass
  185.  
  186.         if database == 'main':
  187.             sqlstr = 'CREATE TABLE IF NOT EXISTS %s.ikeys (ikey TEXT PRIMARY KEY, id INTEGER);' % database
  188.             self.db.execute(sqlstr)
  189.             sqlstr = 'CREATE TABLE IF NOT EXISTS %s.goucima (zi TEXT PRIMARY KEY' % database
  190.             for i in range(self._mlen):
  191.                 sqlstr += ', g%d INTEGER' % i
  192.             
  193.             sqlstr += ');'
  194.             self.db.execute(sqlstr)
  195.             sqlstr = 'CREATE TABLE IF NOT EXISTS %s.pinyin ( plen INTEGER, ' % database
  196.             sqlstr += ''.join(map((lambda x: 'p%d INTEGER, ' % x), range(7)))
  197.             sqlstr += 'zi TEXT, freq INTEGER);'
  198.             self.db.execute(sqlstr)
  199.         
  200.         sqlstr = 'CREATE TABLE IF NOT EXISTS %s.phrases (id INTEGER PRIMARY KEY AUTOINCREMENT,                mlen INTEGER, clen INTEGER, ' % database
  201.         sqlstr += ''.join(map((lambda x: 'm%d INTEGER, ' % x), range(self._mlen)))
  202.         if self._is_chinese:
  203.             sqlstr += 'category INTEGER, '
  204.         
  205.         sqlstr += 'phrase TEXT, freq INTEGER, user_freq INTEGER);'
  206.         self.db.execute(sqlstr)
  207.         self.db.commit()
  208.  
  209.     
  210.     def update_ime(self, attrs):
  211.         '''Update attributes in ime table, attrs is a iterable object
  212.         Like [(attr,val), (attr,val), ...]
  213.         '''
  214.         sqlstr = 'UPDATE main.ime SET val = ? WHERE attr = ?;'
  215.         for attr, val in attrs:
  216.             _sqlstr = 'SELECT * from main.ime WHERE attr = ?'
  217.             res = self.db.execute(_sqlstr, (attr,)).fetchall()
  218.             if res:
  219.                 self.db.execute(sqlstr, (val, attr))
  220.                 continue
  221.         
  222.         self.ime_property_cache = { }
  223.         self._mlen = int(self.get_ime_property('max_key_length'))
  224.         self._is_chinese = self.is_chinese()
  225.         self._set_add_phrase_sqlstr()
  226.         self._pt_index = [
  227.             'id',
  228.             'mlen',
  229.             'clen']
  230.         for i in range(self._mlen):
  231.             self._pt_index.append('m%d' % i)
  232.         
  233.         if self._is_chinese:
  234.             self._pt_index += [
  235.                 'category']
  236.         
  237.         self._pt_index += [
  238.             'phrase',
  239.             'freq',
  240.             'user_freq']
  241.         self.user_can_define_phrase = self.get_ime_property('user_can_define_phrase')
  242.         if self.user_can_define_phrase:
  243.             if self.user_can_define_phrase.lower() == u'true':
  244.                 self.user_can_define_phrase = True
  245.             else:
  246.                 self.user_can_define_phrase = False
  247.         else:
  248.             print 'Could not find "user_can_define_phrase" entry from database, is it a outdated database?'
  249.             self.user_can_define_phrase = False
  250.         self.rules = self.get_rules()
  251.         self.db.commit()
  252.  
  253.     
  254.     def get_rules(self):
  255.         '''Get phrase construct rules'''
  256.         rules = { }
  257.         if self.user_can_define_phrase:
  258.             
  259.             try:
  260.                 _rules = self.get_ime_property('rules')
  261.                 if _rules:
  262.                     _rules = _rules.strip().split(';')
  263.                 
  264.                 for rule in _rules:
  265.                     res = patt_r.match(rule)
  266.                     if res:
  267.                         cms = []
  268.                         if res.group(1) == 'a':
  269.                             rules['above'] = int(res.group(2))
  270.                         
  271.                         _cms = res.group(3).split('+')
  272.                         if len(_cms) > int(self.get_ime_property('max_key_length')):
  273.                             print 'rule: "%s" over max key length' % rule
  274.                             break
  275.                         
  276.                         for _cm in _cms:
  277.                             cm_res = patt_p.match(_cm)
  278.                             cms.append((int(cm_res.group(1)), int(cm_res.group(2))))
  279.                         
  280.                         rules[int(res.group(2))] = cms
  281.                         continue
  282.                     print 'not a legal rule: "%s"' % rule
  283.             except Exception:
  284.                 import traceback
  285.                 traceback.print_exc()
  286.  
  287.             return rules
  288.         return ''
  289.  
  290.     
  291.     def phrase_keys_len(self):
  292.         '''Return the phrase possible key length'''
  293.         max_len = self.rules['above']
  294.         
  295.         try:
  296.             return (map,)((lambda x: len(self.rules[x])), range(2, max_len + 1))[:]
  297.         except:
  298.             return None
  299.  
  300.  
  301.     
  302.     def get_no_check_chars(self):
  303.         '''Get the characters which engine should not change freq'''
  304.         _chars = self.get_ime_property('no_check_chars')
  305.         
  306.         try:
  307.             _chars = _chars.decode('utf-8')
  308.         except:
  309.             pass
  310.  
  311.         return _chars
  312.  
  313.     
  314.     def add_phrases(self, phrases, database = 'main'):
  315.         '''Add phrases to database, phrases is a iterable object
  316.         Like: [(tabkeys, phrase, freq ,user_freq), (tabkeys, phrase, freq, user_freq), ...]
  317.         '''
  318.         map(self.add_phrase, phrases, [
  319.             database] * len(phrases), [
  320.             False] * len(phrases))
  321.         self.db.commit()
  322.  
  323.     
  324.     def add_new_phrases(self, nphrases, database = 'main'):
  325.         '''Add new phrases into db, new phrases is a object
  326.         of [(phrase,freq), (phrase,freq),...]'''
  327.         n_phrases = []
  328.         for _ph, _freq in nphrases:
  329.             
  330.             try:
  331.                 _tabkey = self.parse_phrase_to_tabkeys(_ph)
  332.                 if not self.check_phrase_internal(_ph, _tabkey, database):
  333.                     n_phrases.append((_tabkey, _ph, _freq, 0))
  334.             continue
  335.             print '"%s" would not been added' % _ph
  336.             continue
  337.  
  338.         
  339.         if n_phrases:
  340.             self.add_phrases(n_phrases, database)
  341.         
  342.  
  343.     
  344.     def u_add_phrase(self, nphrase):
  345.         '''Add a phrase to userdb'''
  346.         self.add_phrase(nphrase, database = 'user_db', commit = False)
  347.  
  348.     
  349.     def _set_add_phrase_sqlstr(self):
  350.         '''Create the sqlstr for add phrase according to self._mlen.'''
  351.         sqlstr = 'INSERT INTO %s.phrases ( mlen, clen, '
  352.         sql_suffix = 'VALUES ( ?, ?, '
  353.         mmlen = range(self._mlen)
  354.         sqlstr += ''.join(map((lambda x: 'm%d, ' % x), mmlen))
  355.         sql_suffix += ''.join(map((lambda x: '?, '), mmlen))
  356.         if self._is_chinese:
  357.             sqlstr += 'category, '
  358.             sql_suffix += '?, '
  359.         
  360.         sqlstr += 'phrase, freq, user_freq) '
  361.         sql_suffix += '?, ?, ? );'
  362.         sqlstr += sql_suffix
  363.         self._add_phrase_sqlstr = sqlstr
  364.  
  365.     
  366.     def add_phrase(self, aphrase, database = 'main', commit = True):
  367.         '''Add phrase to database, phrase is a object of
  368.         (tabkeys, phrase, freq ,user_freq)
  369.         '''
  370.         sqlstr = self._add_phrase_sqlstr
  371.         
  372.         try:
  373.             (tabkeys, phrase, freq, user_freq) = aphrase
  374.         except:
  375.             (tabkeys, phrase, freq) = aphrase
  376.             user_freq = 0
  377.  
  378.         if self._is_chinese:
  379.             category = 0
  380.             if type(phrase) != type(u''):
  381.                 phrase = phrase.decode('utf8')
  382.             
  383.             
  384.             try:
  385.                 phrase.encode('gb2312')
  386.                 category |= 1
  387.             except:
  388.                 if '\xe3\x80\x87'.decode('utf8') in phrase:
  389.                     category |= 1
  390.                 
  391.  
  392.             
  393.             try:
  394.                 phrase.encode('big5hkscs')
  395.                 category |= 2
  396.             except:
  397.                 if category & 1:
  398.                     pass
  399.                 else:
  400.                     
  401.                     try:
  402.                         phrase.encode('gbk')
  403.                         category |= 1
  404.  
  405.  
  406.             if not category & (1 | 2):
  407.                 category |= 4
  408.             
  409.         
  410.         
  411.         try:
  412.             tbks = self.parse(tabkeys)
  413.             if len(tbks) != len(tabkeys):
  414.                 print 'In %s %s: we parse tabkeys fail' % (phrase, tabkeys)
  415.                 return None
  416.             record = [
  417.                 None] * (5 + self._mlen)
  418.             record[0] = len(tabkeys)
  419.             record[1] = len(phrase)
  420.             record[2:2 + len(tabkeys)] = (map,)((lambda x: tbks[x].get_key_id()), range(0, len(tabkeys)))
  421.             if self._is_chinese:
  422.                 record += [
  423.                     None]
  424.                 record[-4] = category
  425.             
  426.             record[-3:] = (phrase, freq, user_freq)
  427.             self.db.execute(sqlstr % database, record)
  428.             if commit:
  429.                 self.db.commit()
  430.         except Exception:
  431.             import traceback
  432.             traceback.print_exc()
  433.  
  434.  
  435.     
  436.     def add_goucima(self, gcms):
  437.         '''Add goucima into database, gcms is iterable object
  438.         Like gcms = [(zi,goucima),(zi,goucima), ...]
  439.         '''
  440.         count = 1
  441.         for zi, gcm in gcms:
  442.             _con = ''
  443.             _val = ''
  444.             _len = min(len(gcm), self._mlen)
  445.             for i in range(_len):
  446.                 _con += ', g%d' % i
  447.                 _val += ', ?'
  448.             
  449.             sqlstr = 'INSERT INTO main.goucima ( zi %s )\n            VALUES ( ? %s );' % (_con, _val)
  450.             
  451.             try:
  452.                 gc = self.parse(gcm)
  453.                 if len(gc) != len(gcm):
  454.                     error_m = u'%s %s: Can not parse goucima' % (zi, gcm)
  455.                     raise Exception(error_m.encode('utf8'))
  456.                 len(gc) != len(gcm)
  457.                 record = [
  458.                     zi]
  459.                 for i in range(_len):
  460.                     record.append(gc[i].get_key_id())
  461.                 
  462.                 self.db.execute(sqlstr, record)
  463.             except Exception:
  464.                 import traceback
  465.                 traceback.print_exc()
  466.  
  467.             count += 1
  468.         
  469.         self.db.commit()
  470.  
  471.     
  472.     def add_pinyin(self, pinyins, database = 'main'):
  473.         '''Add pinyin to database, pinyins is a iterable object
  474.         Like: [(zi,pinyin, freq), (zi, pinyin, freq), ...]
  475.         '''
  476.         sqlstr = 'INSERT INTO %s.pinyin ( plen, '
  477.         sql_suffix = 'VALUES ( ?, '
  478.         for i in range(7):
  479.             sqlstr += 'p%d, ' % i
  480.             sql_suffix += '?, '
  481.         
  482.         sqlstr += 'zi, freq ) '
  483.         sql_suffix += '?, ? );'
  484.         sqlstr += sql_suffix
  485.         count = 1
  486.         for pinyin, zi, freq in pinyins:
  487.             
  488.             try:
  489.                 pinyin_n = pinyin.replace('1', '!').replace('2', '@').replace('3', '#').replace('4', '$').replace('5', '%')
  490.                 py = self.parse(pinyin_n)
  491.                 if len(py) != len(pinyin_n):
  492.                     error_m = u'%s %s: Can not parse pinyin' % (zi, pinyin)
  493.                     raise Exception(error_m.encode('utf8'))
  494.                 len(py) != len(pinyin_n)
  495.                 record = [
  496.                     None] * 10
  497.                 record[0] = len(pinyin_n)
  498.                 for i in range(0, len(pinyin_n)):
  499.                     record[1 + i] = py[i].get_key_id()
  500.                 
  501.                 record[-2] = zi
  502.                 record[-1] = freq
  503.                 self.db.execute(sqlstr % database, record)
  504.             except Exception:
  505.                 print count, ': ', zi.encode('utf8'), ' ', pinyin
  506.                 import traceback
  507.                 traceback.print_exc()
  508.  
  509.             count += 1
  510.         
  511.         self.db.commit()
  512.  
  513.     
  514.     def optimize_database(self, database = 'main'):
  515.         sqlstr = '\n            CREATE TABLE tmp AS SELECT * FROM %(database)s.phrases;\n            DELETE FROM %(database)s.phrases;\n            INSERT INTO %(database)s.phrases SELECT * FROM tmp ORDER BY\n            %(tabkeystr)s mlen ASC, user_freq DESC, freq DESC, id ASC;\n            DROP TABLE tmp;\n            CREATE TABLE tmp AS SELECT * FROM %(database)s.goucima;\n            DELETE FROM %(database)s.goucima;\n            INSERT INTO %(database)s.goucima SELECT * FROM tmp ORDER BY zi,g0,g1;\n            DROP TABLE tmp;\n            CREATE TABLE tmp AS SELECT * FROM %(database)s.pinyin;\n            DELETE FROM %(database)s.pinyin;\n            INSERT INTO %(database)s.pinyin SELECT * FROM tmp ORDER BY p0,p1,p2,p3,p4,p5,plen ASC;\n            DROP TABLE tmp;\n            '
  516.         tabkeystr = ''
  517.         for i in range(self._mlen):
  518.             tabkeystr += 'm%d, ' % i
  519.         
  520.         self.db.executescript(sqlstr % {
  521.             'database': database,
  522.             'tabkeystr': tabkeystr })
  523.         self.db.executescript('VACUUM;')
  524.         self.db.commit()
  525.  
  526.     
  527.     def drop_indexes(self, database):
  528.         """Drop the index in database to reduce it's size"""
  529.         sqlstr = '\n            DROP INDEX IF EXISTS %(database)s.goucima_index_z;\n            DROP INDEX IF EXISTS %(database)s.pinyin_index_i;\n            DROP INDEX IF EXISTS %(database)s.phrases_index_p;\n            DROP INDEX IF EXISTS %(database)s.phrases_index_i;\n            VACUUM; \n            ' % {
  530.             'database': database }
  531.         self.db.executescript(sqlstr)
  532.         self.db.commit()
  533.  
  534.     
  535.     def create_indexes(self, database, commit = True):
  536.         sqlstr = '\n            DROP INDEX IF EXISTS %(database)s.goucima_index_z;\n            CREATE INDEX IF NOT EXISTS %(database)s.goucima_index_z ON goucima (zi);\n            DROP INDEX IF EXISTS %(database)s.pinyin_index_i;\n            CREATE INDEX IF NOT EXISTS %(database)s.pinyin_index_i ON pinyin (p0,p1,p2,p3,p4,p5,plen ASC, freq DESC);\n            VACUUM; \n            ' % {
  537.             'database': database }
  538.         sqlstr_t = '\n            DROP INDEX IF EXISTS %(database)s.phrases_index_p;\n            CREATE INDEX IF NOT EXISTS %(database)s.phrases_index_p ON phrases\n            (%(tabkeystr)s mlen ASC, freq DESC, id ASC);\n            DROP INDEX IF EXISTS %(database)s.phrases_index_i;\n            CREATE INDEX IF NOT EXISTS %(database)s.phrases_index_i ON phrases (phrase, mlen ASC);\n            '
  539.         tabkeystr = ''
  540.         for i in range(self._mlen):
  541.             tabkeystr += 'm%d,' % i
  542.         
  543.         if database == 'main':
  544.             sqlstr = sqlstr_t % {
  545.                 'database': database,
  546.                 'tabkeystr': tabkeystr } + sqlstr
  547.         else:
  548.             sqlstr = sqlstr_t % {
  549.                 'database': database,
  550.                 'tabkeystr': tabkeystr }
  551.         self.db.executescript(sqlstr)
  552.         if commit:
  553.             self.db.commit()
  554.         
  555.  
  556.     
  557.     def compare(self, x, y):
  558.         if not cmp(x[1], y[1]) and -cmp(x[-1], y[-1]) and -cmp(x[-2], y[-2]):
  559.             pass
  560.         return cmp(x[0], y[0])
  561.  
  562.     
  563.     def select_words(self, tabkeys, onechar = False, bitmask = 0):
  564.         '''
  565.         Get phrases from database by tab_key objects
  566.         ( which should be equal or less than the max key length)
  567.         This method is called in table.py by passing UserInput held data
  568.         Return result[:] 
  569.         '''
  570.         _len = min(len(tabkeys), self._mlen)
  571.         _condition = ''
  572.         _condition += ''.join(map((lambda x: 'AND m%d = ? ' % x), range(_len)))
  573.         if onechar:
  574.             _condition += 'AND clen=1 '
  575.         
  576.         if bitmask:
  577.             all_ints = xrange(1, 5)
  578.             need_ints = (filter,)((lambda x: x & bitmask), all_ints)
  579.             bit_condition = 'OR'.join(map((lambda x: ' category = %d ' % x), need_ints))
  580.             _condition += 'AND (%s) ' % bit_condition
  581.         
  582.         w_len = (self._mlen - _len) + 1
  583.         x_len = 2
  584.         while x_len <= w_len + 1:
  585.             sqlstr = 'SELECT * FROM (SELECT * FROM main.phrases WHERE mlen < %(mk)d  %(condition)s \n            UNION ALL\n            SELECT * FROM user_db.phrases WHERE mlen < %(mk)d %(condition)s \n            UNION ALL\n            SELECT * FROM mudb.phrases WHERE mlen < %(mk)d %(condition)s )\n            ORDER BY mlen ASC, user_freq DESC, freq DESC, id ASC;' % {
  586.                 'mk': _len + x_len,
  587.                 'condition': _condition }
  588.             _tabkeys = map(int, tabkeys[:_len])
  589.             _tabkeys += _tabkeys + _tabkeys
  590.             result = self.db.execute(sqlstr, _tabkeys).fetchall()
  591.             if len(result) > 0:
  592.                 break
  593.             
  594.             x_len += 1
  595.         sysdb = { }
  596.         usrdb = { }
  597.         mudb = { }
  598.         _cand = []
  599.         searchres = map((lambda res: [
  600. int(res[-2]),
  601. int(res[-1]),
  602. [
  603. (res[1:-2], [
  604. res[:-1],
  605. res[-1:]])]]), result)
  606.         reslist = filter((lambda x: not x[1]), searchres)
  607.         (map,)((lambda x: sysdb.update(x[2])), reslist)
  608.         reslist = filter((lambda x: if x[0] in (0, -1):
  609. passx[1]), searchres)
  610.         (map,)((lambda x: usrdb.update(x[2])), reslist)
  611.         reslist = filter((lambda x: if x[0] not in (0, -1):
  612. passx[1]), searchres)
  613.         (map,)((lambda x: mudb.update(x[2])), reslist)
  614.         searchres = (map,)((lambda key: mudb[key][0] + mudb[key][1]), mudb)
  615.         map(_cand.append, searchres)
  616.         searchres = (None, map)((lambda key: if not not mudb.has_key(key) or usrdb[key][0] + usrdb[key][1]:
  617. pass), usrdb)
  618.         searchres = filter((lambda x: bool(x)), searchres)
  619.         map(_cand.append, searchres)
  620.         searchres = (None, None, map)((lambda key: if not not mudb.has_key(key) or not usrdb.has_key(key) or sysdb[key][0] + sysdb[key][1]:
  621. pass), sysdb)
  622.         searchres = filter((lambda x: bool(x)), searchres)
  623.         map(_cand.append, searchres)
  624.         _cand.sort(cmp = self.compare)
  625.         return _cand[:]
  626.  
  627.     
  628.     def select_zi(self, tabkeys):
  629.         '''
  630.         Get zi from database by tab_key objects
  631.         ( which should be equal or less than 6)
  632.         This method is called in table.py by passing UserInput held data
  633.         Return  result[:] 
  634.         '''
  635.         _len = min(len(tabkeys), 7)
  636.         _condition = ''
  637.         _condition += ''.join(map((lambda x: 'AND p%d = ? ' % x), range(_len)))
  638.         if _len < 7:
  639.             if _len < 3:
  640.                 x_len = 3
  641.             else:
  642.                 x_len = _len + 1
  643.         else:
  644.             x_len = _len
  645.         while x_len < 8:
  646.             sqlstr = 'SELECT * FROM main.pinyin WHERE plen < %(mk)d  %(condition)s \n                ORDER BY plen ASC, freq DESC;' % {
  647.                 'mk': x_len,
  648.                 'condition': _condition }
  649.             _tabkeys = map(int, tabkeys[:_len])
  650.             result = self.db.execute(sqlstr, _tabkeys).fetchall()
  651.             if len(result) > 0:
  652.                 break
  653.             
  654.             x_len += 1
  655.         return result[:]
  656.  
  657.     
  658.     def get_ime_property(self, attr):
  659.         '''get IME property from database, attr is the string of property,
  660.         which should be str.lower() :)
  661.         '''
  662.         if attr not in self.ime_property_cache:
  663.             sqlstr = 'SELECT val FROM main.ime WHERE attr = ?'
  664.             _result = self.db.execute(sqlstr, (attr,)).fetchall()
  665.             if _result:
  666.                 self.ime_property_cache[attr] = _result[0][0]
  667.             else:
  668.                 self.ime_property_cache[attr] = None
  669.         
  670.         return self.ime_property_cache[attr]
  671.  
  672.     
  673.     def get_phrase_table_index(self):
  674.         '''get a list of phrase table columns name'''
  675.         return self._pt_index[:]
  676.  
  677.     
  678.     def generate_userdb_desc(self):
  679.         
  680.         try:
  681.             sqlstring = 'CREATE TABLE IF NOT EXISTS user_db.desc (name PRIMARY KEY, value);'
  682.             self.db.executescript(sqlstring)
  683.             sqlstring = 'INSERT OR IGNORE INTO user_db.desc  VALUES (?, ?);'
  684.             self.db.execute(sqlstring, ('version', '0.4'))
  685.             sqlstring = 'INSERT OR IGNORE INTO user_db.desc  VALUES (?, DATETIME("now", "localtime"));'
  686.             self.db.execute(sqlstring, ('create-time',))
  687.             self.db.commit()
  688.         except:
  689.             import traceback
  690.             traceback.print_exc()
  691.  
  692.  
  693.     
  694.     def init_user_db(self, db_file):
  695.         if not path.exists(db_file):
  696.             db = sqlite3.connect(db_file)
  697.             db.execute('PRAGMA page_size = 4096;')
  698.             db.execute('PRAGMA cache_size = 20000;')
  699.             db.execute('PRAGMA temp_store = MEMORY; ')
  700.             db.execute('PRAGMA synchronous = OFF; ')
  701.             db.commit()
  702.         
  703.  
  704.     
  705.     def get_database_desc(self, db_file):
  706.         if not path.exists(db_file):
  707.             return None
  708.         
  709.         try:
  710.             db = sqlite3.connect(db_file)
  711.             db.execute('PRAGMA page_size = 4096;')
  712.             db.execute('PRAGMA cache_size = 20000;')
  713.             db.execute('PRAGMA temp_store = MEMORY; ')
  714.             db.execute('PRAGMA synchronous = OFF; ')
  715.             desc = { }
  716.             for row in db.execute('SELECT * FROM desc;').fetchall():
  717.                 desc[row[0]] = row[1]
  718.             
  719.             self.db.commit()
  720.             return desc
  721.         except:
  722.             path.exists(db_file)
  723.             return None
  724.  
  725.  
  726.     
  727.     def get_table_phrase_len(self, db_file):
  728.         table_patt = re.compile('.*\\((.*)\\)')
  729.         if not path.exists(db_file):
  730.             return 0
  731.         
  732.         try:
  733.             db = sqlite3.connect(db_file)
  734.             tp_res = db.execute("select sql from sqlite_master                    where name='phrases';").fetchall()
  735.             self.db.commit()
  736.             res = table_patt.match(tp_res[0][0])
  737.             if res:
  738.                 tp = res.group(1).split(',')
  739.                 return len(tp)
  740.             return 0
  741.         except:
  742.             path.exists(db_file)
  743.             return 0
  744.  
  745.  
  746.     
  747.     def cache_goucima(self):
  748.         self._goucima = { }
  749.         goucima = self.db.execute('SELECT * FROM main.goucima;').fetchall()
  750.         (map,)((lambda x: self._goucima.update({
  751. x[0]: x[1:] })), goucima)
  752.  
  753.     
  754.     def get_gcm_id(self, zi):
  755.         '''Get goucima of given character'''
  756.         if self._goucima:
  757.             if not isinstance(zi, unicode):
  758.                 zi = zi.decode('utf-8')
  759.             
  760.             
  761.             try:
  762.                 gcds = self._goucima[zi]
  763.                 return gcds
  764.  
  765.         
  766.         sqlstr = 'SELECT %s FROM main.goucima WHERE zi =?;' % ','.join(map((lambda x: 'g%d' % x), range(self._mlen)))
  767.         return self.db.execute(sqlstr, (zi,)).fetchall()[0]
  768.  
  769.     
  770.     def parse_phrase(self, phrase):
  771.         '''Parse phrase to get its Table code'''
  772.         
  773.         try:
  774.             phrase = unicode(phrase)
  775.         except:
  776.             phrase = phrase.decode('utf8')
  777.  
  778.         p_len = len(phrase)
  779.         tabkeylist = []
  780.         if p_len < 2:
  781.             return []
  782.         
  783.         try:
  784.             if p_len >= self.rules['above']:
  785.                 rule = self.rules[self.rules['above']]
  786.             elif p_len in self.rules:
  787.                 rule = self.rules[p_len]
  788.             else:
  789.                 raise Exception('unsupport len of phrase')
  790.             if p_len < 2(rule) > self._mlen:
  791.                 raise Exception('fault rule: %s' % rule)
  792.             p_len < 2(rule) > self._mlen
  793.             tabkeylist = (None, map)((lambda x: self.get_gcm_id(phrase[x[0] - 1])[x[1] - 1]), rule)
  794.             return [
  795.                 len(tabkeylist)] + [
  796.                 p_len] + tabkeylist[:] + [
  797.                 phrase]
  798.         except:
  799.             p_len < 2
  800.             print 'pharse pharse "%s" fail.' % phrase.encode('utf-8')
  801.  
  802.  
  803.     
  804.     def parse_phrase_to_tabkeys(self, phrase):
  805.         '''Get the Table encoding of the phrase in string form'''
  806.         
  807.         try:
  808.             tabres = self.parse_phrase(phrase)[2:-1]
  809.         except:
  810.             tabres = None
  811.  
  812.         if tabres:
  813.             tabkeys = u''.join(map(self.deparse, tabres))
  814.         else:
  815.             tabkeys = u''
  816.         return tabkeys
  817.  
  818.     
  819.     def check_phrase(self, phrase, tabkey = None, database = 'main'):
  820.         if type(phrase) != type(u''):
  821.             phrase = phrase.decode('utf8')
  822.         
  823.         if self.user_can_define_phrase:
  824.             self.check_phrase_internal(phrase, tabkey, database)
  825.         else:
  826.             map(self.check_phrase_internal, phrase)
  827.  
  828.     
  829.     def check_phrase_internal(self, phrase, tabkey = None, database = 'main'):
  830.         '''Check word freq and user_freq
  831.         '''
  832.         if type(phrase) != type(u''):
  833.             phrase = phrase.decode('utf8')
  834.         
  835.         if self._is_chinese:
  836.             if phrase in tabdict.chinese_nocheck_chars:
  837.                 return None
  838.         
  839.         if len(phrase) >= 2:
  840.             
  841.             try:
  842.                 wordattr = self.parse_phrase(phrase)
  843.                 _len = len(wordattr) - 3
  844.             return None
  845.  
  846.         
  847.         if not tabkey or len(tabkey) > self._mlen:
  848.             sqlstr = 'SELECT * FROM (SELECT * FROM main.phrases WHERE phrase = ?\n            UNION ALL SELECT * FROM user_db.phrases WHERE phrase = ?\n            UNION ALL SELECT * FROM mudb.phrases WHERE phrase = ?)\n            ORDER BY user_freq DESC, freq DESC, id ASC;\n            '
  849.             result = self.db.execute(sqlstr, (phrase, phrase, phrase)).fetchall()
  850.         else:
  851.             tabks = self.parse(tabkey)
  852.             tabkids = tuple(map(int, tabks))
  853.             condition = ' and '.join(map((lambda x: 'm%d = ?' % x), range(len(tabks))))
  854.             sqlstr = 'SELECT * FROM \n            (\n                SELECT * FROM main.phrases WHERE phrase = ? and %(cond)s\n                UNION ALL SELECT * FROM user_db.phrases WHERE phrase = ? and %(cond)s\n                UNION ALL SELECT * FROM mudb.phrases WHERE phrase = ? and %(cond)s\n            )\n            ORDER BY user_freq DESC, freq DESC, id ASC;\n            ' % {
  855.                 'cond': condition }
  856.             result = self.db.execute(sqlstr, ((phrase,) + tabkids) * 3).fetchall()
  857.             if not bool(result):
  858.                 sqlstr = 'SELECT * FROM (SELECT * FROM main.phrases WHERE phrase = ?\n                UNION ALL SELECT * FROM user_db.phrases WHERE phrase = ?\n                UNION ALL SELECT * FROM mudb.phrases WHERE phrase = ?)\n                ORDER BY user_freq DESC, freq DESC, id ASC;\n                '
  859.                 result = self.db.execute(sqlstr, (phrase, phrase, phrase)).fetchall()
  860.             
  861.         sysdb = { }
  862.         usrdb = { }
  863.         mudb = { }
  864.         searchres = map((lambda res: [
  865. int(res[-2]),
  866. int(res[-1]),
  867. [
  868. (res[1:-2], [
  869. res[:-1],
  870. res[-1]])]]), result)
  871.         reslist = filter((lambda x: not x[1]), searchres)
  872.         (map,)((lambda x: sysdb.update(x[2])), reslist)
  873.         reslist = filter((lambda x: if x[0] in (0, -1):
  874. passx[1]), searchres)
  875.         (map,)((lambda x: usrdb.update(x[2])), reslist)
  876.         reslist = filter((lambda x: if x[0] not in (0, -1):
  877. passx[1]), searchres)
  878.         (map,)((lambda x: mudb.update(x[2])), reslist)
  879.         tabkey = ''
  880.         if len(phrase) >= 2:
  881.             tabkey = u''.join(map(self.deparse, wordattr[2:2 + _len]))
  882.         
  883.         if self._is_chinese:
  884.             sqlstr = 'UPDATE mudb.phrases SET user_freq = ? WHERE mlen = ? AND clen = ? %s AND category = ? AND phrase = ?;'
  885.         else:
  886.             sqlstr = 'UPDATE mudb.phrases SET user_freq = ? WHERE mlen = ? AND clen = ? %s AND phrase = ?;'
  887.         
  888.         try:
  889.             if len(phrase) == 1:
  890.                 if not self.dynamic_adjust:
  891.                     return None
  892.                 keyout = (filter,)((lambda k: mudb.has_key(k)), usrdb.keys())
  893.                 map(usrdb.pop, keyout)
  894.                 keyout = (self.dynamic_adjust, filter)((lambda k: if not mudb.has_key(k):
  895. passusrdb.has_key(k)), sysdb.keys())
  896.                 map(sysdb.pop, keyout)
  897.                 (None, None, map)((lambda res: self.db.execute(sqlstr % ''.join(map((lambda x: 'AND m%d = ? ' % x), range(res[0]))), [
  898.                         mudb[res][1] + 1] + list(res[:2 + res[0]]) + list(res[2 + self._mlen:]))
  899. ), mudb.keys())
  900.                 self.db.commit()
  901.                 (None, None, map)((lambda res: self.add_phrase((''.join(map(self.deparse, res[2:2 + int(res[0])])), phrase, 1, usrdb[res][1] + 1), database = 'mudb')), usrdb.keys())
  902.                 (None, map)((lambda res: self.add_phrase((''.join(map(self.deparse, res[2:2 + int(res[0])])), phrase, 2, 1), database = 'mudb')), sysdb.keys())
  903.             elif len(result) == 0 and self.user_can_define_phrase:
  904.                 self.add_phrase((tabkey, phrase, -2, 1), database = 'mudb')
  905.             elif len(result) > 0:
  906.                 if not self.dynamic_adjust:
  907.                     return None
  908.                 keyout = (filter,)((lambda k: mudb.has_key(k)), usrdb.keys())
  909.                 map(usrdb.pop, keyout)
  910.                 keyout = (self.dynamic_adjust, filter)((lambda k: if not mudb.has_key(k):
  911. passusrdb.has_key(k)), sysdb.keys())
  912.                 map(sysdb.pop, keyout)
  913.                 (None, None, map)((lambda res: self.db.execute(sqlstr % ''.join(map((lambda x: 'AND m%d = ? ' % x), range(res[0]))), [
  914.                         mudb[res][1] + 1] + list(res[:2 + res[0]]) + list(res[2 + self._mlen:]))
  915. ), mudb.keys())
  916.                 self.db.commit()
  917.                 (None, None, map)((lambda res: None((self.add_phrase, ''.join(map(self.deparse, res[2:2 + int(res[0])])), phrase if usrdb[res][0][-1] == -1 else 1, usrdb[res][1] + 1), database = 'mudb')), usrdb.keys())
  918.                 (None, map)((lambda res: self.add_phrase((''.join(map(self.deparse, res[2:2 + int(res[0])])), phrase, 2, 1), database = 'mudb')), sysdb.keys())
  919.         except:
  920.             import traceback
  921.             traceback.print_exc()
  922.  
  923.  
  924.     
  925.     def find_zi_code(self, zi):
  926.         '''Check word freq and user_freq
  927.         '''
  928.         zi = zi.decode('utf8')
  929.         sqlstr = 'SELECT * FROM main.phrases WHERE phrase = ?\n        ORDER BY mlen ASC;\n'
  930.         result = self.db.execute(sqlstr, (zi,)).fetchall()
  931.         codes = []
  932.         
  933.         try:
  934.             if result:
  935.                 for _res in result:
  936.                     tabkey = u''
  937.                     for i in range(int(_res[1])):
  938.                         tabkey += self.deparse(_res[3 + i])
  939.                     
  940.                     codes.append(tabkey)
  941.                 
  942.         except:
  943.             import traceback
  944.             traceback.print_exc()
  945.  
  946.         return codes[:]
  947.  
  948.     
  949.     def remove_phrase(self, phrase, database = 'user_db'):
  950.         '''Remove phrase from database, default is from user_db
  951.         phrase should be the a row of select * result from database
  952.         Like (id, mlen,clen,m0,m1,m2,m3,phrase,freq,user_freq)
  953.         '''
  954.         _ph = list(phrase[:-2])
  955.         _condition = ''
  956.         for i in range(_ph[1]):
  957.             _condition += 'AND m%d = ? ' % i
  958.         
  959.         nn = _ph.count(None)
  960.         if nn:
  961.             for i in range(nn):
  962.                 _ph.remove(None)
  963.             
  964.         
  965.         if self._is_chinese:
  966.             msqlstr = 'SELECT * FROM %(database)s.phrases WHERE mlen = ? and clen = ? %(condition)s AND category = ? AND phrase = ? ;' % {
  967.                 'database': database,
  968.                 'condition': _condition }
  969.         else:
  970.             msqlstr = 'SELECT * FROM %(database)s.phrases WHERE mlen = ? and clen = ? %(condition)s AND phrase = ? ;' % {
  971.                 'database': database,
  972.                 'condition': _condition }
  973.         if self.db.execute(msqlstr, _ph[1:]).fetchall():
  974.             if self._is_chinese:
  975.                 sqlstr = 'DELETE FROM %(database)s.phrases WHERE mlen = ? AND clen =? %(condition)s AND category = ? AND phrase = ?  ;' % {
  976.                     'database': database,
  977.                     'condition': _condition }
  978.             else:
  979.                 sqlstr = 'DELETE FROM %(database)s.phrases WHERE mlen = ? AND clen =? %(condition)s AND phrase = ?  ;' % {
  980.                     'database': database,
  981.                     'condition': _condition }
  982.             self.db.execute(sqlstr, _ph[1:])
  983.             self.db.commit()
  984.         
  985.         if self._is_chinese:
  986.             msqlstr = 'SELECT * FROM mudb.phrases WHERE mlen = ? and clen = ? %(condition)s AND category = ? AND phrase = ? ;' % {
  987.                 'condition': _condition }
  988.         else:
  989.             msqlstr = 'SELECT * FROM mudb.phrases WHERE mlen = ? and clen = ? %(condition)s AND phrase = ? ;' % {
  990.                 'condition': _condition }
  991.         if self.db.execute(msqlstr, _ph[1:]).fetchall():
  992.             if self._is_chinese:
  993.                 sqlstr = 'DELETE FROM mudb.phrases WHERE mlen = ? AND clen =? %(condition)s AND category = ? AND phrase = ?  ;' % {
  994.                     'condition': _condition }
  995.             else:
  996.                 sqlstr = 'DELETE FROM mudb.phrases WHERE mlen = ? AND clen =? %(condition)s AND phrase = ?  ;' % {
  997.                     'condition': _condition }
  998.             self.db.execute(sqlstr, _ph[1:])
  999.             self.db.commit()
  1000.         
  1001.  
  1002.     
  1003.     def extra_user_phrases(self, udb, only_defined = False):
  1004.         '''extract user phrases from database'''
  1005.         
  1006.         try:
  1007.             db = sqlite3.connect(udb)
  1008.         except:
  1009.             return None
  1010.  
  1011.         if only_defined:
  1012.             _phrases = db.execute('SELECT clen, phrase, freq, sum(user_freq)                    FROM phrases                     WHERE freq=-1 AND mlen != 0                     GROUP BY clen,phrase;').fetchall()
  1013.         else:
  1014.             _phrases = db.execute('SELECT clen, phrase, freq, sum(user_freq)                    FROM phrases                    WHERE mlen !=0                     GROUP BY clen,phrase;').fetchall()
  1015.         db.commit()
  1016.         return _phrases[:]
  1017.  
  1018.  
  1019.